#ifndef IRQ_H
#define IRQ_H

#include "utility/Types.h"
#include "utility/Instruction.h"
#include "Const.h"

typedef struct ExceptionFrame {
    // segment register
    int gs, fs, es, ds;
    // general register
    int edi, esi, ebp, esp, ebx, edx, ecx, eax;
    int interruptNumber, errorCode;
    int eip;     // Value of EIP (instruction pointer) at exception
    int cs;      // Value of CS segment register
    int eflags;  // Value of EFLAGS register
    int esp3;    // Value of user ESP (if privilege level change)
    int ss3;     // Value of SS segment register (if privilege level change)
} ExceptionFrameType;

typedef void (*InterruptionHandler)(void);

void HandleDivideException();            // 除零异常
void HandleDebugException();             // 调试异常
void HandleNMIException();               // 非屏蔽中断
void HandleBreakpointException();        // 断点异常
void HandleOverflowException();          // 溢出异常
void HandleOutOfBoundException();        // 越界异常
void HandleInvalidOpcodeException();     // 无效操作码异常
void HandleDeviceNotAvailableException();// 协处理器不存在异常
void HandleDoubleFaultException();       // 双重故障
void HandleInvalidTSSException();        // 无效TSS
void HandleSegmentNotPresentException(); // 段不存在
void HandleStackException();             // 堆栈异常
void HandleGeneralProtectionException(); // 常规保护异常
void HandlePageFaultException();         // 页故障
void HandleFloatingPointException();     // 浮点异常
void HandleAlignmentCheckException();    // 对齐检查
void HandleMachineCheckException();      // 机器检查
void HandleSIMDException();              // SIMD浮点异常
void HandleVirtualizationException();    // 虚拟化异常

void SetInterruptionHandler();
void DefaultExceptionHandler(ExceptionFrameType* frame);

// #define IDT_GATE_ATTR   GATE_TYPE_INTERRUPT | GATE_D_32 | GATE_DPL_0 | GATE_P
#define IDT_GATE_ATTR   GATE_TYPE_INTERRUPT | GATE_D_32 | GATE_DPL_0 | GATE_P


uint32_t DisableInterrupts();
void EnableInterrupts(uint32_t value);


static inline void EnableAllInterrupts(void)
{
    Sti();
}

static inline void DisableAllInterrupts(void)
{
    Cli();
}


#endif